package com.zouxw.utils.json;

import com.zouxw.utils.json.controller.FileController;
import com.zouxw.utils.json.controller.JsonController;
import com.zouxw.utils.json.model.JsonModel;
import com.zouxw.utils.json.utils.AppConfig;
import com.zouxw.utils.json.utils.MemoryManager;
import com.zouxw.utils.json.utils.KeyboardShortcutManager;
import com.zouxw.utils.json.view.JsonTreeView;
import com.zouxw.utils.json.view.SchemaValidationDialog;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * EnhancedJson树状查看器 - MVC架构版本
 * 使用MVC设计模式重构的JSON查看器主类
 * 
 * @author zouxw
 * @version 2.0
 */
public class EnhancedJsonTreeViewerV2 extends JFrame {
    
    // ==================== MVC组件 ====================
    /** JSON控制器 */
    private JsonController jsonController;
    
    /** 文件控制器 */
    private FileController fileController;
    
    /** 内存管理器 */
    private MemoryManager memoryManager;
    
    /** 快捷键管理器 */
    private KeyboardShortcutManager shortcutManager;
    
    // ==================== UI组件 ====================
    /** JSON输入区域 */
    private JTextArea jsonInputArea;
    
    /** 搜索字段 */
    private JTextField searchField;
    
    /** 状态标签 */
    private JLabel statusLabel;
    
    /** JSON树形视图 */
    private JsonTreeView jsonTreeView;
    
    // ==================== 构造函数 ====================
    
    /**
     * 构造函数
     */
    public EnhancedJsonTreeViewerV2() {
        initializeFrame();
        initializeControllers();
        initializeComponents();
        setupLayout();
        setupEventListeners();
        loadSampleData();
    }
    
    // ==================== 初始化方法 ====================
    
    /**
     * 初始化主窗口
     */
    private void initializeFrame() {
        setTitle(AppConfig.WINDOW_TITLE);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(AppConfig.WINDOW_WIDTH, AppConfig.WINDOW_HEIGHT);
        setLayout(new BorderLayout(5, 5));
        setLocationRelativeTo(null);
    }
    
    /**
     * 初始化控制器
     */
    private void initializeControllers() {
        jsonController = new JsonController(this);
        fileController = new FileController(this);
        memoryManager = new MemoryManager();
        shortcutManager = new KeyboardShortcutManager(this.getContentPane());
        
        // 启动内存监控
        startMemoryMonitoring();
        
        // 注册快捷键
        registerKeyboardShortcuts();
    }
    
    /**
     * 初始化UI组件
     */
    private void initializeComponents() {
        // 创建JSON输入区域
        jsonInputArea = new JTextArea();
        jsonInputArea.setFont(AppConfig.DEFAULT_FONT);
        JScrollPane inputScrollPane = new JScrollPane(jsonInputArea);
        inputScrollPane.setPreferredSize(new Dimension(AppConfig.WINDOW_WIDTH, AppConfig.INPUT_AREA_HEIGHT));
        
        // 创建状态栏
        statusLabel = new JLabel(AppConfig.STATUS_READY);
        statusLabel.setBorder(BorderFactory.createEtchedBorder());
        
        // 创建JSON树形视图
        jsonTreeView = new JsonTreeView();
        
        // 初始化控制器与视图的连接
        jsonController.initialize(jsonTreeView);
    }
    
    /**
     * 设置布局
     */
    private void setupLayout() {
        // 设置菜单栏
        setJMenuBar(createMenuBar());
        
        // 创建主面板，使用垂直分割
        JSplitPane mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        mainSplitPane.setDividerLocation(AppConfig.INPUT_AREA_HEIGHT);
        mainSplitPane.setResizeWeight(0.3); // 输入区域占30%
        
        // 创建顶部输入面板
        JPanel inputPanel = new JPanel(new BorderLayout(5, 5));
        inputPanel.add(new JLabel(AppConfig.LABEL_JSON_INPUT), BorderLayout.NORTH);
        
        JScrollPane inputScrollPane = new JScrollPane(jsonInputArea);
        inputScrollPane.setPreferredSize(new Dimension(AppConfig.WINDOW_WIDTH, AppConfig.INPUT_AREA_HEIGHT));
        inputPanel.add(inputScrollPane, BorderLayout.CENTER);
        
        // 创建底部树形视图面板
        JPanel treePanel = new JPanel(new BorderLayout());
        treePanel.add(jsonTreeView, BorderLayout.CENTER);
        
        // 设置分割面板的内容
        mainSplitPane.setTopComponent(inputPanel);
        mainSplitPane.setBottomComponent(treePanel);
        
        // 创建底部面板
        JPanel bottomPanel = new JPanel(new BorderLayout());
        JPanel buttonPanel = createButtonPanel();
        bottomPanel.add(buttonPanel, BorderLayout.CENTER);
        bottomPanel.add(statusLabel, BorderLayout.SOUTH);
        
        // 添加组件到主窗口
        add(createToolBar(), BorderLayout.NORTH);
        add(mainSplitPane, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.SOUTH);
    }
    
    /**
     * 创建菜单栏
     * 
     * @return 菜单栏
     */
    private JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        
        // 文件菜单
        JMenu fileMenu = new JMenu(AppConfig.MENU_FILE);
        JMenuItem openItem = new JMenuItem(AppConfig.MENU_OPEN);
        JMenuItem saveItem = new JMenuItem(AppConfig.MENU_SAVE);
        JMenuItem exitItem = new JMenuItem(AppConfig.MENU_EXIT);
        
        openItem.addActionListener(this::handleOpenFile);
        saveItem.addActionListener(this::handleSaveFile);
        exitItem.addActionListener(e -> System.exit(0));
        
        fileMenu.add(openItem);
        fileMenu.add(saveItem);
        fileMenu.addSeparator();
        fileMenu.add(exitItem);
        
        // 编辑菜单
        JMenu editMenu = new JMenu(AppConfig.MENU_EDIT);
        
        // 撤销菜单项
        JMenuItem undoItem = new JMenuItem("撤销 (Ctrl+Z)");
        undoItem.addActionListener(e -> handleUndo());
        editMenu.add(undoItem);
        
        // 重做菜单项
        JMenuItem redoItem = new JMenuItem("重做 (Ctrl+Y)");
        redoItem.addActionListener(e -> handleRedo());
        editMenu.add(redoItem);
        
        editMenu.addSeparator();
        
        // 格式化菜单项
        JMenuItem formatItem = new JMenuItem(AppConfig.MENU_FORMAT + " (Ctrl+Shift+F)");
        formatItem.addActionListener(e -> handleFormatJson(true));
        editMenu.add(formatItem);
        
        // 压缩菜单项
        JMenuItem compressItem = new JMenuItem(AppConfig.MENU_COMPRESS + " (Ctrl+Shift+C)");
        compressItem.addActionListener(e -> handleFormatJson(false));
        editMenu.add(compressItem);
        
        editMenu.addSeparator();
        
        // 清空内容菜单项
        JMenuItem clearItem = new JMenuItem("清空内容 (Ctrl+Delete)");
        clearItem.addActionListener(e -> {
            jsonInputArea.setText("");
            updateStatus("内容已清空");
        });
        editMenu.add(clearItem);
        
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        
        return menuBar;
    }
    
    /**
     * 创建工具栏
     * 
     * @return 工具栏
     */
    private JToolBar createToolBar() {
        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);
        
        // 打开按钮
        JButton openButton = new JButton(AppConfig.MENU_OPEN);
        openButton.addActionListener(this::handleOpenFile);
        toolBar.add(openButton);
        
        // 保存按钮
        JButton saveButton = new JButton(AppConfig.MENU_SAVE);
        saveButton.addActionListener(this::handleSaveFile);
        toolBar.add(saveButton);
        
        toolBar.addSeparator();
        
        // 格式化按钮
        JButton formatButton = new JButton(AppConfig.MENU_FORMAT);
        formatButton.addActionListener(e -> handleFormatJson(true));
        toolBar.add(formatButton);
        
        // 压缩按钮
        JButton compressButton = new JButton(AppConfig.MENU_COMPRESS);
        compressButton.addActionListener(e -> handleFormatJson(false));
        toolBar.add(compressButton);
        
        toolBar.addSeparator();
        
        // 搜索组件
        JPanel searchPanel = createSearchPanel();
        toolBar.add(searchPanel);
        
        return toolBar;
    }
    
    /**
     * 创建搜索面板
     * 
     * @return 搜索面板
     */
    private JPanel createSearchPanel() {
        JPanel searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 2));
        searchPanel.add(new JLabel(AppConfig.LABEL_SEARCH));
        
        searchField = new JTextField(AppConfig.SEARCH_FIELD_WIDTH);
        searchPanel.add(searchField);
        
        // 搜索按钮
        JButton searchButton = new JButton(AppConfig.BUTTON_SEARCH);
        searchButton.addActionListener(this::handleSearch);
        searchPanel.add(searchButton);
        
        // 清除搜索按钮
        JButton clearSearchButton = new JButton(AppConfig.BUTTON_CLEAR);
        clearSearchButton.addActionListener(this::handleClearSearch);
        searchPanel.add(clearSearchButton);
        
        return searchPanel;
    }
    
    /**
     * 创建按钮面板
     * 
     * @return 按钮面板
     */
    private JPanel createButtonPanel() {
        JPanel buttonPanel = new JPanel();
        
        // 撤销按钮
        JButton undoButton = new JButton("撤销 (Ctrl+Z)");
        undoButton.addActionListener(e -> handleUndo());
        undoButton.setEnabled(false);
        buttonPanel.add(undoButton);
        
        // 重做按钮
        JButton redoButton = new JButton("重做 (Ctrl+Y)");
        redoButton.addActionListener(e -> handleRedo());
        redoButton.setEnabled(false);
        buttonPanel.add(redoButton);
        
        buttonPanel.add(new JSeparator(SwingConstants.VERTICAL));
        
        // 解析JSON按钮
        JButton parseButton = new JButton(AppConfig.BUTTON_PARSE_JSON + " (Ctrl+Enter)");
        parseButton.addActionListener(this::handleParseJson);
        buttonPanel.add(parseButton);
        
        // 展开所有按钮
        JButton expandAllButton = new JButton("展开所有 (Ctrl+E)");
        expandAllButton.addActionListener(e -> jsonController.expandAllNodes());
        buttonPanel.add(expandAllButton);
        
        // 折叠所有按钮
        JButton collapseAllButton = new JButton("折叠所有 (Ctrl+Shift+E)");
        collapseAllButton.addActionListener(e -> jsonController.collapseAllNodes());
        buttonPanel.add(collapseAllButton);
        
        buttonPanel.add(new JSeparator(SwingConstants.VERTICAL));
        
        // Schema验证按钮
        JButton schemaButton = new JButton("Schema验证 (Ctrl+Shift+V)");
        schemaButton.addActionListener(e -> handleSchemaValidation());
        buttonPanel.add(schemaButton);
        
        return buttonPanel;
    }
    
    /**
     * 设置事件监听器
     */
    private void setupEventListeners() {
        // 添加输入监听器，实时验证JSON
        jsonInputArea.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                handleJsonInputChange();
            }
            
            @Override
            public void removeUpdate(DocumentEvent e) {
                handleJsonInputChange();
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {
                handleJsonInputChange();
            }
        });
        
        // 搜索字段回车事件
        searchField.addActionListener(this::handleSearch);
    }
    
    /**
     * 加载示例数据
     */
    private void loadSampleData() {
        String sampleJson = "{\n" +
                "  \"name\": \"John Doe\",\n" +
                "  \"age\": 30,\n" +
                "  \"isStudent\": false,\n" +
                "  \"address\": {\n" +
                "    \"street\": \"123 Main St\",\n" +
                "    \"city\": \"Anytown\",\n" +
                "    \"zip\": \"12345\"\n" +
                "  },\n" +
                "  \"phoneNumbers\": [\n" +
                "    {\n" +
                "      \"type\": \"home\",\n" +
                "      \"number\": \"555-1234\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"type\": \"work\",\n" +
                "      \"number\": \"555-5678\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"children\": [],\n" +
                "  \"scores\": [85, 92, 78, 90],\n" +
                "  \"metadata\": null,\n" +
                "  \"nestedJson\": \"{\\\"key1\\\": \\\"value1\\\", \\\"key2\\\": {\\\"nestedKey\\\": \\\"nestedValue\\\"}}\",\n" +
                "  \"nestedArray\": \"[\\\"item1\\\", \\\"item2\\\", {\\\"objInArray\\\": \\\"value\\\"}]\",\n" +
                "  \"mixedData\": {\n" +
                "    \"regularString\": \"just a string\",\n" +
                "    \"jsonString\": \"{\\\"internalKey\\\": \\\"internalValue\\\"}\",\n" +
                "    \"numberValue\": 42\n" +
                "  }\n" +
                "}";
        
        jsonInputArea.setText(sampleJson);
    }
    
    // ==================== 事件处理方法 ====================
    
    /**
     * 处理打开文件
     * 
     * @param e 事件
     */
    private void handleOpenFile(ActionEvent e) {
        String content = fileController.openFile();
        if (content != null) {
            jsonInputArea.setText(content);
            handleParseJson(e);
        }
    }
    
    /**
     * 处理保存文件
     * 
     * @param e 事件
     */
    private void handleSaveFile(ActionEvent e) {
        String content = jsonInputArea.getText();
        boolean success = fileController.saveFile(content);
        if (success) {
            updateStatus("文件已保存: " + fileController.getCurrentFileName());
        }
    }
    
    /**
     * 处理解析JSON
     * 
     * @param e 事件
     */
    private void handleParseJson(ActionEvent e) {
        String jsonString = jsonInputArea.getText().trim();
        if (jsonString.isEmpty()) {
            updateStatus("请输入JSON字符串");
            return;
        }
        
        System.out.println("开始解析JSON: " + jsonString.substring(0, Math.min(50, jsonString.length())) + "...");
        jsonController.parseJson(jsonString);
        updateStatusFromController();
        System.out.println("JSON解析完成");
    }
    
    /**
     * 处理撤销操作
     */
    private void handleUndo() {
        String jsonContent = jsonController.undo();
        if (jsonContent != null) {
            jsonInputArea.setText(jsonContent);
            updateStatus("撤销: " + jsonController.getUndoDescription());
        }
    }
    
    /**
     * 处理重做操作
     */
    private void handleRedo() {
        String jsonContent = jsonController.redo();
        if (jsonContent != null) {
            jsonInputArea.setText(jsonContent);
            updateStatus("重做: " + jsonController.getRedoDescription());
        }
    }
    
    /**
     * 处理Schema验证
     */
    private void handleSchemaValidation() {
        String jsonContent = jsonInputArea.getText().trim();
        if (jsonContent.isEmpty()) {
            JOptionPane.showMessageDialog(this, "请先输入JSON数据", "提示", JOptionPane.WARNING_MESSAGE);
            return;
        }
        
        // 打开Schema验证对话框
        SchemaValidationDialog dialog = new SchemaValidationDialog(this, jsonContent);
        dialog.setVisible(true);
        
        // 获取验证结果
        com.zouxw.utils.json.utils.JsonSchemaValidator.ValidationResult result = dialog.getLastResult();
        if (result != null) {
            if (result.isValid()) {
                updateStatus("Schema验证通过");
            } else {
                updateStatus("Schema验证失败: " + result.getErrors().size() + " 个错误");
            }
        }
    }
    
    /**
     * 处理格式化JSON
     * 
     * @param pretty 是否美化格式
     */
    private void handleFormatJson(boolean pretty) {
        String jsonString = jsonInputArea.getText().trim();
        if (jsonString.isEmpty()) {
            return;
        }
        
        jsonController.formatJson(pretty);
        String formattedJson = jsonController.getCurrentJsonString();
        if (formattedJson != null) {
            jsonInputArea.setText(formattedJson);
        }
        
        updateStatus(pretty ? AppConfig.STATUS_JSON_FORMATTED : AppConfig.STATUS_JSON_COMPRESSED);
    }
    
    /**
     * 处理搜索
     * 
     * @param e 事件
     */
    private void handleSearch(ActionEvent e) {
        String searchText = searchField.getText().trim();
        if (searchText.isEmpty()) {
            jsonController.clearSearch();
            updateStatus(AppConfig.STATUS_READY);
            return;
        }
        
        boolean found = jsonController.searchNodes(searchText);
        if (found) {
            updateStatus("找到匹配项: " + searchText);
        } else {
            updateStatus("未找到匹配项: " + searchText);
        }
    }
    
    /**
     * 处理清除搜索
     * 
     * @param e 事件
     */
    private void handleClearSearch(ActionEvent e) {
        searchField.setText("");
        jsonController.clearSearch();
        updateStatus(AppConfig.STATUS_READY);
    }
    
    /**
     * 处理JSON输入变化（使用防抖）
     */
    private void handleJsonInputChange() {
        String jsonString = jsonInputArea.getText().trim();
        // 使用防抖验证，避免频繁验证
        jsonController.validateJsonDebounced(jsonString);
    }
    
    // ==================== 状态更新方法 ====================
    
    /**
     * 更新状态标签
     * 
     * @param message 状态消息
     */
    private void updateStatus(String message) {
        statusLabel.setText(message);
        statusLabel.setForeground(Color.BLACK);
    }
    
    /**
     * 从控制器更新状态
     */
    private void updateStatusFromController() {
        JsonModel.ValidationStatus status = jsonController.getValidationStatus();
        updateStatusFromValidation(status);
    }
    
    /**
     * 从验证状态更新状态
     * 
     * @param status 验证状态
     */
    private void updateStatusFromValidation(JsonModel.ValidationStatus status) {
        switch (status) {
            case VALID:
                statusLabel.setText(AppConfig.STATUS_JSON_VALID);
                statusLabel.setForeground(Color.BLACK);
                break;
            case INVALID:
                String errorMessage = jsonController.getValidationErrorMessage();
                statusLabel.setText(AppConfig.ERROR_JSON_FORMAT + errorMessage);
                statusLabel.setForeground(Color.RED);
                break;
            case EMPTY:
                statusLabel.setText(AppConfig.STATUS_READY);
                statusLabel.setForeground(Color.BLACK);
                break;
            case VALIDATING:
                statusLabel.setText("正在验证...");
                statusLabel.setForeground(Color.BLUE);
                break;
            default:
                statusLabel.setText(AppConfig.STATUS_READY);
                statusLabel.setForeground(Color.BLACK);
                break;
        }
    }
    
    // ==================== 内存管理方法 ====================
    
    /**
     * 启动内存监控
     */
    private void startMemoryMonitoring() {
        memoryManager.startMonitoring(
            // 内存警告回调
            status -> {
                SwingUtilities.invokeLater(() -> {
                    updateStatus("内存使用率较高: " + status.getFormattedUsedMemory() + 
                               " / " + status.getFormattedMaxMemory() + 
                               " (" + String.format("%.1f", status.getHeapUsagePercentage()) + "%)");
                    statusLabel.setForeground(Color.ORANGE);
                });
            },
            // 内存危险回调
            status -> {
                SwingUtilities.invokeLater(() -> {
                    updateStatus("内存使用率过高: " + status.getFormattedUsedMemory() + 
                               " / " + status.getFormattedMaxMemory() + 
                               " (" + String.format("%.1f", status.getHeapUsagePercentage()) + "%)");
                    statusLabel.setForeground(Color.RED);
                    
                    // 自动执行垃圾回收
                    memoryManager.performGarbageCollection();
                });
            }
        );
    }
    
    /**
     * 停止内存监控
     */
    private void stopMemoryMonitoring() {
        if (memoryManager != null) {
            memoryManager.stopMonitoring();
        }
    }
    
    /**
     * 获取内存状态信息
     * 
     * @return 内存状态信息
     */
    public String getMemoryStatus() {
        if (memoryManager != null) {
            return memoryManager.getMemoryStatus().toString();
        }
        return "内存监控未启动";
    }
    
    // ==================== 快捷键管理方法 ====================
    
    /**
     * 注册键盘快捷键
     */
    private void registerKeyboardShortcuts() {
        shortcutManager.registerDefaultShortcuts(new KeyboardShortcutManager.ActionListener() {
            @Override
            public void onOpenFile() {
                handleOpenFile(null);
            }
            
            @Override
            public void onSaveFile() {
                handleSaveFile(null);
            }
            
            @Override
            public void onUndo() {
                handleUndo();
            }
            
            @Override
            public void onRedo() {
                handleRedo();
            }
            
            @Override
            public void onFormatJson() {
                handleFormatJson(true);
            }
            
            @Override
            public void onCompressJson() {
                handleFormatJson(false);
            }
            
            @Override
            public void onSearch() {
                if (searchField != null) {
                    searchField.requestFocus();
                }
            }
            
            @Override
            public void onExpandAll() {
                jsonController.expandAllNodes();
            }
            
            @Override
            public void onCollapseAll() {
                jsonController.collapseAllNodes();
            }
            
            @Override
            public void onParseJson() {
                handleParseJson(null);
            }
            
            @Override
            public void onClearContent() {
                jsonInputArea.setText("");
                updateStatus("内容已清空");
            }
            
            @Override
            public void onSchemaValidation() {
                handleSchemaValidation();
            }
        });
    }
    
    // ==================== 窗口关闭处理 ====================
    
    /**
     * 重写窗口关闭方法，确保资源正确释放
     */
    @Override
    protected void processWindowEvent(java.awt.event.WindowEvent e) {
        if (e.getID() == java.awt.event.WindowEvent.WINDOW_CLOSING) {
            // 停止内存监控
            stopMemoryMonitoring();
            
            // 执行垃圾回收
            if (memoryManager != null) {
                memoryManager.performGarbageCollection();
            }
        }
        super.processWindowEvent(e);
    }
    
    // ==================== 主方法 ====================
    
    /**
     * 更新JSON输入区域
     * 
     * @param jsonContent JSON内容
     */
    public void updateJsonInputArea(String jsonContent) {
        if (jsonInputArea != null) {
            jsonInputArea.setText(jsonContent);
        }
    }

    /**
     * 主方法
     * 
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 使用SwingUtilities.invokeLater确保线程安全
        SwingUtilities.invokeLater(() -> {
            // 创建并显示主窗口
            EnhancedJsonTreeViewerV2 viewer = new EnhancedJsonTreeViewerV2();
            viewer.setVisible(true);
        });
    }
}
